// 
// SoapTrace.Net - A soap message monitoring utility. 
// 
// Copyright (C) 2004 Matthew Ward
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// 
// Matthew Ward (mrward@users.sourceforge.net)
// 

using NUnit.Framework;
using System;
using System.IO;
using SoapTrace.Core.Formatters;
using SoapTrace.Core.Communication;
using SoapTrace.Tests.Config;
using SoapTrace.Tests.Utils;

namespace SoapTrace.Tests
{
	/// <summary>
	/// Test fixture to test simple soap message formatting of the
	/// <see cref="SoapTrace.Core.Formatters.SoapMessageFormatter"/>
	/// </summary>
	[ TestFixture ]
	public class SoapFormatterTestFixture
	{
		/// <summary>
		/// The formatter's configuration.
		/// </summary>
		private SoapMessageFormatterConfig m_Config = new SoapMessageFormatterConfig( );
		
		/// <summary>
		/// The soap message formatter under test.
		/// </summary>
		private SoapMessageFormatter m_Formatter = null;

		/// <summary>
		/// The name of the web service that will be passed to the formatter.
		/// </summary>
		private string m_WebServiceName = "Maths";

		/// <summary>
		/// The uri of the web service that will be passed to the formatter.
		/// </summary>
		private string m_Uri = "Maths.asmx";

		/// <summary>
		/// The web service operation's name passed to the formatter.
		/// </summary>
		private string m_WebServiceMethod = "Test";

		/// <summary>
		/// The mock soap message that contains the message to be formatted.
		/// </summary>
		private MockSoapMessage m_MockMessage;

		/// <summary>
		/// The soap response message to be formatted.
		/// </summary>
		private string m_SoapResponseMessage = String.Empty;

		/// <summary>
		/// The expected formatted response.
		/// </summary>
		private string m_ExpectedFormattedResponseXml = String.Empty;

		/// <summary>
		/// The soap request message to be formatted.
		/// </summary>
		private string m_SoapRequestMessage = String.Empty;

		/// <summary>
		/// The expected formatted request.
		/// </summary>
		private string m_ExpectedFormattedRequestXml = String.Empty;

		/// <summary>
		/// Initialises each test.
		/// </summary>
		[ SetUp ]
		public void Init( )
		{
			StringReader Reader = new StringReader( GetConfigXml( ) );
			m_Config = SoapMessageFormatterConfig.Load( Reader );

			m_Formatter = new SoapMessageFormatter( m_Config.WebServices );

			m_MockMessage = new MockSoapMessage( );
		}

		/// <summary>
		/// Tests whether the response xml is correctly formatted. 
		/// </summary>
		[ Test ]
		public void ResponseXmlFormatting( )
		{
			SetSoapResponseMessage( );
			SetExpectedFormattedResponseXml( );

			m_MockMessage.SetMessage( m_SoapResponseMessage );

			IMessageFormatter Formatter = ( IMessageFormatter )m_Formatter;
			
			FormattedText FormattedText = Formatter.FormatResponse( String.Empty,
				m_Uri,
				m_WebServiceName, 
				m_WebServiceMethod,
				m_MockMessage );

			string FormattedResponse = FormattedText.Text;

			Assert.AreEqual( m_ExpectedFormattedResponseXml, FormattedResponse );
		}

		/// <summary>
		/// Tests whether the request xml is correctly formatted. 
		/// </summary>
		[ Test ]
		public void RequestXmlFormatting( )
		{
			SetSoapRequestMessage( );
			SetExpectedFormattedRequestXml( );

			m_MockMessage.SetMessage( m_SoapRequestMessage );

			IMessageFormatter Formatter = ( IMessageFormatter )m_Formatter;

			FormattedText FormattedText = Formatter.FormatRequest( String.Empty,
				m_Uri,
				m_WebServiceName,
				m_WebServiceMethod,
				m_MockMessage );
			string FormattedRequest = FormattedText.Text;

			Assert.AreEqual( m_ExpectedFormattedRequestXml, FormattedRequest );
		}

		/// <summary>
		/// Tests whether the request xml is correctly formatted even
		/// though some of the parameters passed are passed as strings
		/// and not xml.  This makes sure we can gracefully handle the case
		/// where the parameters are not xml but just plain strings. 
		/// </summary>
		[ Test ]
		public void RequestXmlFormattingWithStringXmlParts( )
		{
			SetSoapRequestMessageWithStringXmlParts( );
			SetExpectedFormattedRequestXmlWithStringXmlParts( );

			m_MockMessage.SetMessage( m_SoapRequestMessage );

			IMessageFormatter Formatter = ( IMessageFormatter )m_Formatter;

			FormattedText FormattedText = Formatter.FormatRequest( String.Empty,
				m_Uri,
				m_WebServiceName,
				m_WebServiceMethod,
				m_MockMessage );
			string FormattedRequest = FormattedText.Text;

			Assert.AreEqual( m_ExpectedFormattedRequestXml, FormattedRequest );
		}
		
		/// <summary>
		/// Tests that a parameter is not displayed if the config has
		/// Display=false.
		/// </summary>
		[ Test ]
		public void NonDisplayingParameter( )
		{
			// Override the config so the first request parameter
			// of the web service Test is not displayed.
			
			WebService WebService = m_Config.WebServices.Find( "Maths" );
			WebServiceOperation Operation = WebService.Operations.Find( "Test" );
			Operation.Parameters[ 0 ].Display = false;
			
			m_Formatter = new SoapMessageFormatter( m_Config.WebServices );
			
			// Test the formatting.
			
			SetSoapRequestMessage( );
			SetExpectedRequestXmlWithNonDisplayedParameter( );

			m_MockMessage.SetMessage( m_SoapRequestMessage );

			IMessageFormatter Formatter = ( IMessageFormatter )m_Formatter;

			FormattedText FormattedText = Formatter.FormatRequest( String.Empty,
				m_Uri,
				m_WebServiceName,
				m_WebServiceMethod,
				m_MockMessage );
			string FormattedRequest = FormattedText.Text;

			Assert.AreEqual( m_ExpectedFormattedRequestXml, FormattedRequest );			
		}
		
		/// <summary>
		/// Tests that a return value is not displayed if the config has
		/// Display=false.
		/// </summary>
		[ Test ]
		public void NonDisplayingReturnValue( )
		{
			// Override the config so the first response return value
			// of the web service Test is not displayed.
			
			WebService WebService = m_Config.WebServices.Find( "Maths" );
			WebServiceOperation Operation = WebService.Operations.Find( "Test" );
			Operation.ReturnValue.Items[ 0 ].Display = false;
			
			m_Formatter = new SoapMessageFormatter( m_Config.WebServices );
			
			// Test the formatting.
			
			SetSoapResponseMessage( );
			SetExpectedResponseXmlWithNonDisplayedReturnValue( );

			m_MockMessage.SetMessage( m_SoapResponseMessage );

			IMessageFormatter Formatter = ( IMessageFormatter )m_Formatter;

			FormattedText FormattedText = Formatter.FormatResponse( String.Empty,
				m_Uri,
				m_WebServiceName,
				m_WebServiceMethod,
				m_MockMessage );
			string FormattedResponse = FormattedText.Text;

			Assert.AreEqual( m_ExpectedFormattedResponseXml, FormattedResponse );			
		}

		/// <summary>
		/// Set the soap messsage's soap response.
		/// </summary>
		private void SetSoapResponseMessage( )
		{
			m_SoapResponseMessage = @"<?xml version='1.0' encoding='utf-8'?>" +
				"<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" +
				"<soap:Body>" +
				"<TestResponse xmlns='http://tempuri.org/'>" +
				"<TestResult>" +
				"<string>&lt;ticket&gt;&lt;user&gt;matt&lt;/user&gt;&lt;password&gt;secret&lt;/password&gt;&lt;/ticket&gt;</string>" +
				"<string>&lt;hello&gt;world&lt;/hello&gt;</string>" +
				"</TestResult>" +
				"</TestResponse>" +
				"</soap:Body>" +
				"</soap:Envelope>";
		}

		/// <summary>
		/// Sets the expected formatted response xml.
		/// </summary>
		private void SetExpectedFormattedResponseXml( )
		{
			m_ExpectedFormattedResponseXml = "TestResponse\r\n\r\nstring: \r\n<ticket>\r\n\t<user>matt</user>\r\n\t<password>secret</password>\r\n</ticket>\r\n\r\nstring: \r\n<hello>world</hello>\r\n\r\n";
		}
		
		/// <summary>
		/// Sets the expected formatted response xml when the first
		/// return value should not be displayed.
		/// </summary>
		private void SetExpectedResponseXmlWithNonDisplayedReturnValue( )
		{
			m_ExpectedFormattedResponseXml = "TestResponse\r\n\r\nstring: \r\n<hello>world</hello>\r\n\r\n";
		}
		
		/// <summary>
		/// Sets the soap message request.
		/// </summary>
		private void SetSoapRequestMessage( )
		{
			m_SoapRequestMessage = @"<?xml version='1.0' encoding='utf-8'?>" +
				"<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" +
				"<soap:Body>" +
				"<Test xmlns='http://tempuri.org/'>" +
				"<xml>&lt;ticket&gt;&lt;user&gt;matt&lt;/user&gt;&lt;password&gt;secret&lt;/password&gt;&lt;/ticket&gt;</xml>" +
				"<text>Test</text>" +
				"</Test>" +
				"</soap:Body>" +
				"</soap:Envelope>";
		}

		/// <summary>
		/// Sets the expected formatted request xml.
		/// </summary>
		private void SetExpectedFormattedRequestXml( )
		{
			m_ExpectedFormattedRequestXml = "Test\r\n" +
				"\r\n" +
				"xml: \r\n" +
				"<ticket>\r\n" +
				"\t<user>matt</user>\r\n" +
				"\t<password>secret</password>\r\n" +
				"</ticket>\r\n" +
				"\r\n" +
				"text: Test" +
				"\r\n";
		}

		
		/// <summary>
		/// Sets the expected formatted request xml when the first parameter
		/// is not to be displayed.
		/// </summary>
		private void SetExpectedRequestXmlWithNonDisplayedParameter( )
		{
			m_ExpectedFormattedRequestXml = "Test\r\n\r\ntext: Test\r\n";			
		}

		/// <summary>
		/// Sets the soap message request with strings instead of xml like parameters.
		/// </summary>
		private void SetSoapRequestMessageWithStringXmlParts( )
		{
			m_SoapRequestMessage = @"<?xml version='1.0' encoding='utf-8'?>" +
				"<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>" +
				"<soap:Body>" +
				"<Test xmlns='http://tempuri.org/'>" +
				"<xml>First string.</xml>" +
				"<text>Test</text>" +
				"</Test>" +
				"</soap:Body>" +
				"</soap:Envelope>";
		}

		/// <summary>
		/// Sets the expected formatted request xml with strings instead
		/// of xml like parameters.
		/// </summary>
		private void SetExpectedFormattedRequestXmlWithStringXmlParts( )
		{
			m_ExpectedFormattedRequestXml = "Test\r\n\r\nxml: First string.\r\ntext: Test\r\n";
		}
		
		/// <summary>
		/// Gets the configuration xml for the Soap message formatter object under
		/// test.
		/// </summary>
		/// <returns>The configuration xml.</returns>
		private string GetConfigXml( )
		{
			string Xml = "<soapmessageformatter.config xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
				"	<webservice name='Maths' uri='Maths.asmx'>" +
				"		<operation name='Test'>" +
				"			<params>" +
				"				<param type='xml' name='string' display='true' />" +
				"				<param type='string' name='test' display='true' />" +
				"			</params>" +
				"			<returnValue type='xml.array' name='' display='true'>" +
				"				<item type='xml' name='' display='true' />" +
				"				<item type='xml' name='' display='true' />" +
				"			</returnValue>" +
				"		</operation>" +
				"		<operation name='Add'>" +
				"			<params>" +
				"				<param type='string' name='Value1' display='true' />" +
				"				<param type='string' name='Value2' display='true' />" +
				"			</params>" +
				"			<returnValue type='string' name='AddResult' display='true' />" +
				"		</operation>" +
				"	</webservice>" +
				"</soapmessageformatter.config> ";

				
			return Xml;
		}
	}
}
